package com.beadwallet.alarm.service.email;

import java.security.Security;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import com.beadwallet.alarm.util.StringUtil;
import com.beadwallet.common.enums.CodeEnum;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BrSendMailI {

    private static Logger logger = LoggerFactory.getLogger(BrSendMailI.class);

    private static final Integer initSize = 1;

    public static String smtp = "smtp.mxhichina.com";
    public static String[] respException;
    public static String addressException;
    public static String authFaild;
    public static LinkedBlockingQueue<JSONObject> linkedQueue = null;
    private static BrSendMailI brSendMailI = new BrSendMailI();
    public static boolean flagThread = false;
    public static int queueDelay = 10;
    /**
     * 记录异常发生的次数
     */
    public static Map<Integer, Integer> mapException = new ConcurrentHashMap<>();

    public static void params(String[] respException0, String addressExceptions, String authFailds, String queueDelay0, String smtp0, int queueSize) {
        smtp = smtp0;
        queueDelay = Integer.parseInt(queueDelay0);
        respException = respException0;
        addressException = addressExceptions;
        authFaild = authFailds;
        linkedQueue = new LinkedBlockingQueue<>(queueSize);
    }

    public static BrSendMailI getMailInstance() {
        return brSendMailI;
    }


    /**
     * 群发邮件
     *
     //* @param mailType 只有sendAlarmPresonal自定义的类型 发送失败邮件才会重发
     * @param sendType 选择使用哪个发件人
     * @param to       收件人
     * @param subject  邮件主题
     * @param content  邮件内容
     *                 //* @param __current ice 内置对象
     * @return
     */
    public String sendToMails(String sendType, String[] to, String subject, String content) {
        Properties props = new Properties();
        logger.info("sendType : {}", sendType);
        try {
            JSONObject sendTypeJson = JSONObject.fromObject(sendType);
            props.put("mail.smtp.user", sendTypeJson.get("senderAddr"));
            props.put("mail.smtp.password", sendTypeJson.get("senderPwd"));
            Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
            final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
            //设置邮件会话参数
            //邮箱的发送服务器地址
            props.setProperty("mail.smtp.host", smtp);
            props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
            props.setProperty("mail.smtp.socketFactory.fallback", "false");
            //邮箱发送服务器端口,这里设置为465端口
            props.setProperty("mail.smtp.port", "465");
            props.setProperty("mail.smtp.socketFactory.port", "465");
            props.setProperty("mail.transport.protocol", "smtp");
            props.put("mail.smtp.auth", "true");
//            props.put("mail.smtp.starttls.enable", "true");
            logger.info("mails : {}", to);
            sendMailConnect(props, to, subject, content);
            return CodeEnum.SUCC.getCode();
        } catch (Exception e) {
            logger.error("sendToMails--Exception:{}", e);
            /*//javax.mail.internet.AddressException: Illegal address   地址不合法异常
            if (e.getMessage().contains(addressException)) {
                return ContansData.ADDRESSEXCEPTION;
            }
            if ("sendAlarmPresonal".equals(mailType)) {
                for (int i = 0; i < respException.length; i++) {
                    if (e.getMessage().contains(respException[i]) || e.toString().indexOf(authFaild) > 0) { // 网络异常，提前返回
                        final MailObject mailObject = new MailObject();
                        mailObject.setContent(content);
                        mailObject.setSubject(subject);
                        mailObject.setProps(props);
                        mailObject.setTo(to);
                        mailObject.setExceptionCode(exceptionCode);

                        PropertiesUtil.executorService.execute(() -> {

                            try {

                                if (!linkedQueue.contains(JSONObject.fromObject(mailObject))) {
                                    logger.info("add queue jsondata : {}", JSONObject.fromObject(mailObject));
                                    linkedQueue.add(JSONObject.fromObject(mailObject)); // 容量不足抛出异常
                                }

                            } catch (Exception e1) {// 重发，出现异常放入队列 后续处理
                                logger.error("Queue is full ", e1);
                                //CurdService.getInstance().save(mailObject.getExceptionCode(), JSONObject.fromObject(mailObject).toString(), ContansData.MAILFLAG);

                            }
                            mapException.put(mailObject.getExceptionCode(), StringUtil.isNotEmpty(mapException.get(mailObject.getExceptionCode())) ? mapException.get(mailObject.getExceptionCode()) + 1 : initSize);
                        });
                        return ContansData.INTELBLOKING;
//                        break;
                    }
                }
                return ContansData.ERROR;

            } else {*/
            //sendAlarm 不进行操作
            return CodeEnum.FAILURE.getCode();
        }

    }


    public void sendMailConnect(Properties props, String[] to, String subject, String content) throws Exception {

        Session sendMailSession =  Session.getDefaultInstance(props, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(props.getProperty("mail.smtp.user"), props.getProperty("mail.smtp.password"));
            }
        });
        Message newMessage = new MimeMessage(sendMailSession);
        Address[] address = new InternetAddress[to.length];
        for (int i = 0; i < to.length; i++) {
            address[i] = new InternetAddress(to[i]);
        }
        // 接收方邮件地
        newMessage.setRecipients(Message.RecipientType.TO, address);
        if(subject != null){
            newMessage.setSubject(subject);
        }else{
            newMessage.setSubject(null);
        }
        newMessage.setSentDate(new Date());
        newMessage.setText(content);
        newMessage.setHeader("Content-Type", "text/html;\n  charset=\"utf-8\"");
        newMessage.setFrom(new InternetAddress(props.getProperty("mail.smtp.user")));
//        Transport transport = sendMailSession.getTransport("smtp");
//        newMessage.setFrom(new InternetAddress(props.getProperty("mail.smtp.user")));
////        transport.connect(BrSendMailI.smtp, props.getProperty("mail.smtp.user"), props.getProperty("mail.smtp.password"));
//        transport.sendMessage(newMessage, newMessage.getRecipients(Message.RecipientType.TO));
        Transport transport = sendMailSession.getTransport();
        transport.connect();
        transport.sendMessage(newMessage, newMessage.getAllRecipients());
        transport.close();
        //Transport.send(newMessage);
        logger.info(subject + " sends success!!");
    }


    public void repeatSend() {

        if (!flagThread) {
            flagThread = true;
            JSONObject jsonObj = null;
            while ((jsonObj = linkedQueue.poll()) != null) {
                try {
                    Random rand = new Random();
                    Thread.sleep((rand.nextInt(10) + queueDelay) * 1000);
                    logger.info(jsonObj.getString("subject") + "--thread send");
                    JSONArray jsonArray = jsonObj.getJSONArray("to");
                    String temp[] = new String[jsonArray.size()];
                    for (int i = 0; i < jsonArray.size(); i++) {
                        temp[i] = jsonArray.getString(i);
                    }

                    Properties props = new Properties();
                    JSONObject property = jsonObj.getJSONObject("props");
                    props.put("mail.smtp.user", property.getString("mail.smtp.user"));
                    props.put("mail.smtp.password", property.getString("mail.smtp.password"));
                    sendMailConnect(props, temp, jsonObj.getString("subject") + (StringUtil.isNotEmpty(mapException.get(jsonObj.getInt("exceptionCode"))) ? "  >>>> Already appear : " + mapException.get(jsonObj.getInt("exceptionCode")) + " count" : ""), jsonObj.getString("content"));
                    //发送成功,去掉map中的次数
                    mapException.remove(jsonObj.getInt("exceptionCode"));
                } catch (Exception e) {
                    logger.error(jsonObj.getString("subject"), e);
                    for (int i = 0; i < respException.length; i++) {
                        // 可能第一次 由于网络异常，后续重发剔除非网络异常的邮件
                        if (e.getMessage().contains(respException[i])) {
                            try {

                                if (!linkedQueue.contains(jsonObj)) {
                                    // 容量不足抛出异常
                                    linkedQueue.add(jsonObj);
                                }
                            } catch (Exception e2) {
                                logger.error("Queue is full ", e2);
                                //CurdService.getInstance().save(jsonObj.getInt("exceptionCode"), jsonObj.toString(), ContansData.MAILFLAG);
                            }
                            mapException.put(jsonObj.getInt("exceptionCode"), StringUtil.isNotEmpty(mapException.get(jsonObj.getInt("exceptionCode"))) ? mapException.get(jsonObj.getInt("exceptionCode")) + 1 : initSize);
                            break;
                        }
                    }

                }
            }

            flagThread = false;
        }

    }


    public static String getSmtp() {
        return smtp;
    }

    /*public static void main(String[] args) {

        LinkedBlockingQueue<JSONObject> linkedQueue1 = new LinkedBlockingQueue<JSONObject>(800);
        JSONObject object0 = new JSONObject();
        String[] str = {"xingxingchy@163.com"};
        object0.put("to", str);
        Properties props = new Properties();
        props.setProperty("xingxingchy@163.com", "520lblmwanm");
        //props.setProperty("ttt233", "67777");
        object0.put("props", props);

        JSONObject object1 = new JSONObject();
        String[] str1 = {"xingxingchy@163.com"};
        object1.put("to", str1);
        Properties props1 = new Properties();
        props1.setProperty("xingxingchy@163.com", "520lblmwanm");
        //props1.setProperty("ttt233", "67777");
        object1.put("props", props1);

        System.out.println(object0);

        JSONObject propertiesq = object1.getJSONObject("props");
        System.out.println(propertiesq.get("xingxingchy@163.com"));

        linkedQueue1.add(object0);
        if (linkedQueue1.contains(object1)) {
            System.out.println("00000");
        } else {
            System.out.println("003333");
        }

    }*/
}
